#include "N1List.h"

N1ListItem::N1ListItem(N1Object *_item, N1ListItem *_next, N1ListItem *_prev)
{
    _item->retain();
    item = _item;
    next = _next;
    prev = _prev;
    if(next) next->prev = this;
    if(prev) prev->next = this;
}

N1ListItem::~N1ListItem()
{
    item->release();
}


N1List::N1List()
{
    m_pHead = m_pTail = NULL;
    m_nCount = 0;
}

N1List::N1List(N1List *list)
{
    N1POSITION pos = list->getHeadPosition();
    while(pos)
    {
        addHead(list->getNext(pos));
    }
}

/*N1List::N1List(N1Array *array)
{
    N1UInt32 count = array->GetCount();

}*/

void N1List::addHead(N1Object *obj)
{
    m_pHead = new N1ListItem(obj, m_pHead, NULL);
    m_nCount++;
}

void N1List::addTail(N1Object *obj)
{
    m_pTail = new N1ListItem(obj, NULL, m_pTail);
    m_nCount++;
}

void N1List::removeAll( )
{
    N1ListItem *item = m_pHead;
    N1ListItem *cur_item;
    while(item)
    {
        cur_item = item;
        item = item->next;
        delete cur_item;
    }
    m_pHead = m_pTail = NULL;
    m_nCount = 0;
}

N1Object* N1List::removeHead( )
{
    N1Object* ret = getHead();
    N1ListItem *head = m_pHead;
    m_pHead = m_pHead->next;
    delete head;
    m_nCount--;
    return ret;
}

N1Object* N1List::removeTail( )
{
    N1Object* ret = getTail();
    N1ListItem *tail = m_pTail;
    m_pTail = m_pTail->prev;
    delete tail;
    m_nCount--;
    return ret;
}

void N1List::removeAt(N1POSITION position)
{
    N1ListItem *item = (N1ListItem*)position;
    N1ListItem *prev = item->prev;
    if(!prev) { //first item
        m_pHead = item->next;
    } else {
        prev->next = item->next;
    }
    delete item;
    m_nCount--;
}

const N1Object* N1List::getHead( ) const
{
    return m_pHead->item;
}

N1Object* N1List::getHead( )
{
    return m_pHead->item;
}

const N1Object* N1List::getTail( ) const
{
    return m_pTail->item;
}

N1Object* N1List::getTail( )
{
    return m_pTail->item;
}

N1POSITION N1List::getHeadPosition( ) const 
{
    return (N1POSITION)m_pHead;
}

N1POSITION N1List::getTailPosition( ) const 
{
    return (N1POSITION)m_pTail;
}

N1Object* N1List::getNext(N1POSITION& rPosition)
{
    N1ListItem *item = (N1ListItem *)rPosition;
    rPosition = (N1POSITION)item->next;
    return item->item;
}

const N1Object* N1List::getNext(N1POSITION& rPosition) const 
{
    N1ListItem *item = (N1ListItem *)rPosition;
    rPosition = (N1POSITION)item->next;
    return item->item;
}

N1Object* N1List::getPrev(N1POSITION& rPosition)
{
    N1ListItem *item = (N1ListItem *)rPosition;
    rPosition = (N1POSITION)item->prev;
    return item->item;
}

const N1Object* N1List::getPrev(N1POSITION& rPosition) const 
{
    N1ListItem *item = (N1ListItem *)rPosition;
    rPosition = (N1POSITION)item->prev;
    return item->item;
}

N1Object* N1List::getAt(N1POSITION position)
{
    N1ListItem *item = (N1ListItem *)position;
    return item->item;
}

const N1Object* N1List::getAt(N1POSITION position) const
{
    N1ListItem *item = (N1ListItem *)position;
    return item->item;
}

void N1List::setAt(N1POSITION pos, N1Object* obj)
{
    N1ListItem *item = (N1ListItem *)pos;
    item->item->release();
    item->item = obj->retain();
}

N1POSITION N1List::insertAfter(N1POSITION position, N1Object* obj)
{
    N1ListItem *item = (N1ListItem *)position;
    N1ListItem *newItem = new N1ListItem(obj, item->next, item);
    return (N1POSITION)newItem;
}

N1POSITION N1List::insertBefore(N1POSITION position, N1Object* obj)
{
    N1ListItem *item = (N1ListItem *)position;
    N1ListItem *newItem = new N1ListItem(obj, item, item->prev);
    return (N1POSITION)newItem;
}

N1POSITION N1List::find(N1Object* obj, N1POSITION startAfter) const
{
    N1POSITION pos = startAfter;
    while(pos)
    {
        if(getNext(pos)==obj)
            return pos;
    }
    return NULL;
}

N1POSITION N1List::findIndex(N1UInt32 nIndex) const
{
    N1POSITION pos = getHeadPosition();
    while(pos && nIndex--)
    {
        getNext(pos);
    }
    return pos;
}

N1UInt32 N1List::getCount() const
{
    return m_nCount;
}

N1UInt32 N1List::getSize( ) const
{
    return m_nCount;
}

BOOL N1List::isEmpty( ) const
{
    return (m_nCount==0);
}
